
#include "SonixCamera.h"

#include "util.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>

#include <time.h>

unsigned long GetTickCount()
{
    struct timespec ts;

    clock_gettime(CLOCK_MONOTONIC, &ts);

    return (ts.tv_sec * 1000 + ts.tv_nsec / 1000000);
}

void SetProgress(void *ptrClass, float fProcess)
{
	printf("fProcess %5f\n", fProcess);
}
char firm_name[300] = {0};
void BurnerFW()
{
	printf("\nburning fw\n");
	char buffer[300];
	char *p = getcwd(buffer, 40);
	char *dir = (char*)get_current_dir_name();
	char fileName[100];
	memset(fileName, 0, 100);
	if(strlen(firm_name) > 5){
		strcpy(fileName,firm_name);
	}else{		
		sprintf(fileName, "%s/%s", dir, "fix_292D-AR0230----SONIX_----2110290001.src"); 
	}
	FILE *fileHandle;
	if(!(fileHandle = fopen(fileName, "rb")))
	{
		printf("open file fail\n");
		return;
	}
	struct stat fileInfo;
	stat(fileName, &fileInfo);
	char *pFW = malloc(fileInfo.st_size + 1);
	printf("fileInfo.st_size = %x\n", (unsigned int)fileInfo.st_size);
	fread(pFW, 1, fileInfo.st_size, fileHandle);
	fclose(fileHandle);
	
	SERIAL_FLASH_TYPE sft;
	SonixCam_GetSerialFlashType(&sft, true);

	printf("start burner fw\n");
	BOOL hr = SonixCam_BurnerFW(pFW, fileInfo.st_size, SetProgress, 0, SFT_ST, FALSE);
	if(hr)
	{
		printf("burner fw success!\n");
		//SonixCam_RestartDevice();
	}
	else
		printf("burner fw fail!\n");
	free(pFW);
	pFW = 0;
}

void BurnerSN()
{
	ChangeParamInfo cp;
	memset(&cp, 0x0, sizeof(cp));
	//cp.pSerialNumber = "SN000100001";
	//cp.SerialNumberLength = 11;
	BYTE vidpid[5] = {0};
	vidpid[0] = 0x0c;
	vidpid[1] = 0x45;
	vidpid[2] = 0x33;
	vidpid[3] = 0x44;
	cp.pVidPid = vidpid;

	char buffer[300];
	char *p = getcwd(buffer, 40);
	char *dir = (char*)get_current_dir_name();
	char fileName[100];
	memset(fileName, 0, 100);
	sprintf(fileName, "%s/%s", dir, "test_fw.src"); 

	FILE *fileHandle;
	if(!(fileHandle = fopen(fileName, "rb")))
	{
		printf("open file fail\n");
		return;
	}
	struct stat fileInfo;
	stat(fileName, &fileInfo);
	char *pFW = malloc(fileInfo.st_size + 1);
	printf("fileInfo.st_size = %x\n", (unsigned int)fileInfo.st_size);
	fread(pFW, 1, fileInfo.st_size, fileHandle);
	fclose(fileHandle);

	SonixCam_SetParamTableFormFWFile(pFW, fileInfo.st_size, &cp, NULL, NULL, SFT_MXIC, NULL);

}

void AsicRegisterWR()
{
	printf("\nasic register read/write:\n");
	unsigned char data[10];
	memset(data, 0, 10);
	SonixCam_AsicRegisterRead(0x101f, data, 1);
	printf("read data :%x\n", data[0]);

	SonixCam_AsicRegisterRead(0x1003, data, 1);
	printf("read data :%x\n", data[0]);
	data[0] = data[0] & 0xFE;
	SonixCam_AsicRegisterWrite(0x1003, data, 1);
	printf("write data :%x\n", data[0]);
	SonixCam_AsicRegisterRead(0x1003, data, 1);
	printf("read data :%x\n\n", data[0]);
}

void SerialFlashWR()
{
	printf("serial flash read/write:\n");
    	DSP_ROM_TYPE romType;
	SonixCam_GetAsicRomType(&romType);
	long sfAddr = 0x1f000;
	if(romType == DRT_64K)
	{
		sfAddr = 0xE000;
	}
	else if(romType == DRT_128K)
	{
		sfAddr = 0x1f000;
	}
	
	unsigned char sfdata[100];
	memset(sfdata, 0, 100);
	SonixCam_SerialFlashRead(sfAddr, sfdata, 15);
	printf("read data :");
	int i = 0;
	for(i = 0; i < 15; i++)
		printf("%2x ", sfdata[i]);
	printf("\n");

	SERIAL_FLASH_TYPE sft;
	SonixCam_GetSerialFlashType(&sft, true);
	if(sft == SFT_UNKNOW)
	{
		sft = SFT_MXIC;
		//sft = SFT_XXXX;
	}
	sprintf(sfdata, "12345678901234567");
	printf("write data :%s\n", "12345678901234567");
	printf("sft == %d , sfAddr = %x\n", sft, (int)sfAddr);
	SonixCam_SerialFlashSectorWrite(sfAddr, sfdata, 15, sft);
	memset(sfdata, 0, 15);
	SonixCam_SerialFlashRead(sfAddr, sfdata, 15);
	printf("read data :");
	for(i = 0; i < 15; i++)
		printf("%2x ", sfdata[i]);
	printf("\n");
	
	BYTE sn[100] = { 0 };
	SonixCam_GetSerialNumber(sn, sizeof(sn));
	printf("sn : %s\n", (char*)sn);

}

#define test_start_addr 0x30000
#define test_data_length 0x1000

void XuTest()
{
	int i = 0;
	if(!SonixCam_EraseSectorFlash(test_start_addr, SFT_GIGA))
		printf("SonixCam_EraseSectorFlash fail!\n");
	sleep(1);

	BYTE recData[test_data_length];
	memset(recData, 0, sizeof(recData));

	for(i = 0; i < test_data_length; i++){
		recData[i] = i % 0x10;
		//recData[i] = 0xFF; 
	}

	int addr = test_start_addr;
	for(i = 0; i < test_data_length; i += 0x20){

		addr = test_start_addr + i;
		ExtensionData temp;
		temp.Addr[0] = addr >> 16;
		temp.Addr[1] = addr >> 8;
		temp.Addr[2] = addr;
		memcpy(temp.Value, recData + i, 0x20);
		temp.Temp = 0x80;
		if (!SonixCam_XuWrite((BYTE*)&temp, sizeof(temp), 0x04, 0x02))
			goto write_fail;
	}
	printf("write data=\n");
	for(i = 0; i < test_data_length; i++){
		if((i % 0x20) == 0)
			printf("\n");
		printf("%02x ", recData[i]);
	}
	printf("\n\n");


	printf("start read\n");
	memset(recData, 0, sizeof(recData));
	for(i = 0; i < test_data_length; i += 0x20){

		addr = test_start_addr + i;
		ExtensionData temp;
		temp.Addr[0] = addr >> 16;
		temp.Addr[1] = addr >> 8;
		temp.Addr[2] = addr;
		temp.Temp = 0x00;
		if (!SonixCam_XuWrite((BYTE*)&temp, sizeof(temp), 0x04, 0x02))
			goto read_fail;
		if (!SonixCam_XuRead((BYTE*)&temp, sizeof(temp), 0x04,  0x02))
			goto read_fail;

		memcpy(recData + i, temp.Value, 0x20);
	}

	printf("read data=\n");
	for(i = 0; i < test_data_length; i++){
		if((i % 0x20) == 0)
			printf("\n");
		printf("%02x ", recData[i]);
	}
	printf("\n");

	return;

read_fail:
	printf("read fail\n");	
	return;
write_fail:
	printf("read fail\n");	
}

int main(int argc, char *argv[])
{
	int i = 0;
	char *vidpid = 0;

	if(argc == 2){
		char *vp = argv[1];
		if(8 == strlen(vp)){
			vidpid=vp;
		}
	}
	if(argc == 3){
		char * vp = argv[2];
		if( strlen(vp) > 5){
			strcpy(firm_name,vp);
		}
	}
	if(strlen(firm_name)> 5){
		printf("use %s firmware\n",firm_name);
	}else{
		printf("use default firmware\n");
	}

	for(i = 0; i < 1; i++)
	{
		if(vidpid == 0){
			vidpid = "0c456366" ; //05a39331  2bc5050b 05a39230 0c4564ab 2bc50509 0c45636b
		}
		if(TRUE != SonixCam_Init(vidpid))
		{
			printf("Could not find/open sonix device, vidpid=%s\n", vidpid);
			vidpid = "0c456366";
			if(TRUE != SonixCam_Init(vidpid))
			{
				printf("Could not find/open sonix device, vidpid=%s\n", vidpid);
				exit(1);
			}
		}
		printf("find device\n");
	}

	// asic register read/write
		//AsicRegisterWR();

	// serial flash read/write
	//	SerialFlashWR();
		
	//Get Camera Info
	unsigned char data[100] = {0};
	//if(SonixCam_GetFwVersionEx(DRT_64K, fwVer, 100, TRUE))
	unsigned long  curCount = GetTickCount();
	SonixCam_GetFwVersion(data, sizeof(data), TRUE);
	//printf("tickCount = %d\n", GetTickCount() - curCount);
	
	printf("FwVersion: %s\n", (char*)data);

	memset(data, 0, sizeof(data));
    SonixCam_GetManufacturer(data, sizeof(data));
	printf("Manufacturer: %s\n", (char*)data);

	memset(data, 0, sizeof(data));
	SonixCam_GetProduct(data, sizeof(data));
	printf("Product: %s\n", (char*)data);

	memset(data, 0, sizeof(data));
	SonixCam_GetVidPid(data, sizeof(data));
	printf("VidPid: %02x%02x%02x%02x\n", data[0], data[1], data[2], data[3]);

	memset(data, 0, sizeof(data));
	SonixCam_GetSerialNumber(data, sizeof(data));
	printf("SerialNumber: %s\n", (char*)data);

	memset(data, 0, sizeof(data));
	SonixCam_GetString3(data, sizeof(data));
	printf("String3: %s\n", (char*)data);

	memset(data, 0, sizeof(data));
	SonixCam_GetInterface(data, sizeof(data));
	printf("Interface: %s\n", (char*)data);

	//burner sn
		//BurnerSN();

	//burner fw
	BurnerFW();
	
	/* 
	//I2c Test
	BYTE data;
	SonixCam_AsicRegisterRead(0x1003, &data, 1);
	printf("SonixCam_AsicRegisterRead =%x\n", data);
	data &= 0xF0;
	SonixCam_AsicRegisterWrite(0X1003, &data, 1);
	SonixCam_AsicRegisterRead(0x1003, &data, 1);
	printf("SonixCam_AsicRegisterRead =%x\n", data);
	data = 0;
	bool hr = SonixCam_SensorRegisterCustomRead(0x36, 0x380c, &data, 1, FALSE);
	if(!hr)
		printf("SonixCam_SensorRegisterCustomRead return false\n");

	printf("SonixCam_SensorRegisterCustomRead = %x \n", data);
	*/


	//Extend xu test
	//XuTest();

	// char buffer[300];
	// char *p = getcwd(buffer, 40);
	// char *dir = (char*)get_current_dir_name();
	// char fileName[100];
	// memset(fileName, 0, 100);
	// sprintf(fileName, "%s/%s", dir, "2279-OV9281----SONIX_SZ--2008200001.src"); 
	// FILE *fileHandle;
	// if(!(fileHandle = fopen(fileName, "rb"))){
	// 	printf("open file fail\n");
	// 	return;
	// }
	// struct stat fileInfo;
	// stat(fileName, &fileInfo);
	// char *pFW = malloc(fileInfo.st_size + 1);
	// printf("fileInfo.st_size = %x\n", (unsigned int)fileInfo.st_size);
	// fread(pFW, 1, fileInfo.st_size, fileHandle);
	// fclose(fileHandle);

	// unsigned char fwVersion[200] = { 0 };
	// SonixCam_GetFwVersionFromFile(pFW, fwVersion, sizeof(fwVersion), false);
	// printf("fwVersion=%s\n", fwVersion);

	SonixCam_UnInit();
}
